package com.tvunetworks.center.user.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.tvunetworks.center.common.constant.LocalConstant;
import com.tvunetworks.center.common.exception.ServerException;
import com.tvunetworks.center.common.model.dto.api.instance.ApiCreateInstanceParam;
import com.tvunetworks.center.common.util.BaseHttpUtil;
import com.tvunetworks.center.common.util.JsonUtil;
import com.tvunetworks.center.common.util.MyUtil;
import com.tvunetworks.center.user.model.result.ResultConstant;
import com.tvunetworks.center.user.model.vo.InstanceVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: tvucc-aggregator
 * @description: InstanceApiUtil
 * @author lebronchen
 * @create: 2020-04-23 14:00
 **/
@Component
@Slf4j
public class InstanceApiUtil {


    @Value("${instance.url.createInstance}")
    private String createInstanceUrl;
    @Value("${instance.url.shutdownInstance}")
    private String shutdownInstanceUrl;
    @Value("${instance.url.listActiveRegionWithRemarkUrl}")
    private String listActiveRegionWithRemarkUrl;
    @Value("${instance.url.listAllIds}")
    private String listAllIdsUrl;
    @Value("${instance.url.getInstance}")
    private String getInstanceUrl;

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private AccessServerUtil accessServerUtil;

    /**
     *
     * @param imageType imageType
     * @return List
     * @throws IOException 编译异常
     */
    public List listActiveRegion(String imageType) throws IOException {
        String url = BaseHttpUtil.formatUrl(listActiveRegionWithRemarkUrl);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add(LocalConstant.API_HEADER_PARAM_KEY, accessServerUtil.generatorAccess());

        Map<String, String> param = new HashMap<>();
        param.put("imageType", imageType);
        HttpEntity httpEntity = new HttpEntity(JsonUtil.toJsonStr(param), headers);

        ResponseEntity<String> responseEntity = null;
        log.error("Instance Service ListActiveRegion url:{} pram:[{}]", url, param);
        try {
            responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);
        } catch (Exception e) {
            log.error("Instance Service ListActiveRegion Http error url:{} pram:[{}]", url, param);
            log.error(e.toString(), e);
            ServerException.Exception(ResultConstant.Instance.CALL_INSTANCE_FAILED.setResult(url));
        }
        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            log.error("Instance Service ListActiveRegion HttpStatus not 200 url:{} pram:[{}] responseEntity:[{}]", url, param, responseEntity);
            Map<String, Object> result = new HashedMap();
            result.put("url", url);
            result.put("statusCode", responseEntity.getStatusCode());
            ServerException.Exception(ResultConstant.Instance.CALL_INSTANCE_FAILED.setResult(result));
        }
        String result = responseEntity.getBody();
        log.error("Instance Service ListActiveRegion HttpStatus result url:{} pram:[{}] result:[{}]", url, param, result);

        JsonNode jsonNode = MyUtil.MAPPER.readTree(result);
        if (!(jsonNode.has("errorCode") && "0x0".equalsIgnoreCase(jsonNode.get("errorCode").asText()))) {
            log.error("Instance Service ListActiveRegion HttpStatus result not success url:{} pram:[{}] result:[{}]", url, param, result);
            ServerException.Exception(ResultConstant.Instance.LIST_ACTIVE_REGION_FAILED.setResult(result));
        }
        List regionList = JsonUtil.convertValue(jsonNode.get("result"), List.class);
        return regionList;
    }

    /**
     *
     * @param param param
     * @return InstanceVo
     * @throws IOException 编译异常
     */
    public InstanceVo createInstance(ApiCreateInstanceParam param) throws IOException {
        String url = BaseHttpUtil.formatUrl(createInstanceUrl);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add(LocalConstant.API_HEADER_PARAM_KEY, accessServerUtil.generatorAccess());

        HttpEntity httpEntity = new HttpEntity(JsonUtil.toJsonStr(param), headers);

        ResponseEntity<String> responseEntity = null;
        log.error("Instance Service CreateInstance url:{} pram:[{}]", url, param);
        try {
            responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);
        } catch (Exception e) {
            log.error("Instance Service CreateInstance Http error url:{} pram:[{}]", url, param);
            log.error(e.toString(), e);
            ServerException.Exception(ResultConstant.Instance.CALL_INSTANCE_FAILED.setResult(url));
        }
        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            log.error("Instance Service CreateInstance HttpStatus not 200 url:{} pram:[{}] responseEntity:[{}]", url, param, responseEntity);
            Map<String, Object> result = new HashedMap();
            result.put("url", url);
            result.put("statusCode", responseEntity.getStatusCode());
            ServerException.Exception(ResultConstant.Instance.CALL_INSTANCE_FAILED.setResult(result));
        }
        String result = responseEntity.getBody();
        log.error("Instance Service CreateInstance HttpStatus result url:{} pram:[{}] result:[{}]", url, param, result);

        JsonNode jsonNode = MyUtil.MAPPER.readTree(result);
        if (!(jsonNode.has("errorCode") && "0x0".equalsIgnoreCase(jsonNode.get("errorCode").asText()))) {
            log.error("Instance Service CreateInstance HttpStatus result not success url:{} pram:[{}] result:[{}]", url, param, result);
            ServerException.Exception(ResultConstant.Instance.CREATE_INSTANCE_FAILED.setResult(result));
        }
        InstanceVo instance = JsonUtil.convertValue(jsonNode.get("result"), InstanceVo.class);
        return instance;
    }

    /**
     *
     * @param instanceId instanceId
     * @throws IOException 编译异常
     */
    public void shutdownInstance(String instanceId) throws IOException {
        String url = BaseHttpUtil.formatUrl(shutdownInstanceUrl);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add(LocalConstant.API_HEADER_PARAM_KEY, accessServerUtil.generatorAccess());

        Map<String, String> param = new HashMap<>();
        param.put("instanceId", instanceId);
        HttpEntity httpEntity = new HttpEntity(JsonUtil.toJsonStr(param), headers);

        ResponseEntity<String> responseEntity = null;
        log.error("Instance Service ShutdownInstance url:{} pram:[{}]", url, param);
        try {
            responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);
        } catch (Exception e) {
            log.error("Instance Service ShutdownInstance Http error url:{} pram:[{}]", url, param);
            log.error(e.toString(), e);
            ServerException.Exception(ResultConstant.Instance.CALL_INSTANCE_FAILED.setResult(url));
        }
        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            log.error("Instance Service ShutdownInstance HttpStatus not 200 url:{} pram:[{}] responseEntity:[{}]", url, param, responseEntity);
            Map<String, Object> result = new HashedMap();
            result.put("url", url);
            result.put("statusCode", responseEntity.getStatusCode());
            ServerException.Exception(ResultConstant.Instance.SHUTDOWN_INSTANCE_FAILED.setResult(result));
        }
        String result = responseEntity.getBody();
        log.error("Instance Service ShutdownInstance HttpStatus result url:{} pram:[{}] result:[{}]", url, param, result);

        JsonNode jsonNode = MyUtil.MAPPER.readTree(result);
        if (!jsonNode.has("errorCode")) {
            log.error("Instance Service ShutdownInstance HttpStatus result not success url:{} pram:[{}] result:[{}]", url, param, result);
            ServerException.Exception(ResultConstant.Instance.SHUTDOWN_INSTANCE_FAILED.setResult(result));
        }
        String errorCode = jsonNode.get("errorCode").asText();
        if ("0x0".equals(errorCode) || "81203107".equals(errorCode)) {
            return;
        }
        log.error("Instance Service ShutdownInstance HttpStatus result not success url:{} pram:[{}] result:[{}]", url, param, result);
        ServerException.Exception(ResultConstant.Instance.SHUTDOWN_INSTANCE_FAILED.setResult(result));
    }

    /**
     *
     * @param imageType imageType
     * @param origin origin
     * @return List
     * @throws IOException 编译异常
     */
    public List<String> listRunningInstance(String imageType, String origin) throws IOException {
        String url = BaseHttpUtil.formatUrl(listAllIdsUrl);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add(LocalConstant.API_HEADER_PARAM_KEY, accessServerUtil.generatorAccess());

        Map<String, String> param = new HashMap<>();
        param.put("imageType", imageType);
        param.put("origin", origin);
        HttpEntity httpEntity = new HttpEntity(JsonUtil.toJsonStr(param), headers);

        ResponseEntity<String> responseEntity;
        log.info("Instance Service listAllIds url:{} pram:[{}]", url, param);
        try {
            responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);
        } catch (RestClientException e) {
            log.error(e.toString(), e);
            log.info("Instance Service listAllIds Http error url:{} pram:[{}]", url, param);
            throw new ServerException(ResultConstant.Instance.CALL_INSTANCE_FAILED.setResult(url));
        }

        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            log.info("Instance Service listAllIds HttpStatus not 200 url:{} pram:[{}] responseEntity:[{}]", url, param, responseEntity);
            throw new ServerException(ResultConstant.Instance.LIST_INSTANCE_FAILED.setResult(url));
        }
        String result = responseEntity.getBody();
        log.info("Instance Service listAllIds HttpStatus result url:{} pram:[{}] result:[{}]", url, param, result);

        JsonNode jsonNode = MyUtil.MAPPER.readTree(result);
        if (!(jsonNode.has("errorCode") && "0x0".equalsIgnoreCase(jsonNode.get("errorCode").asText()))) {
            log.info("Instance Service listAllIds HttpStatus result not success url:{} pram:[{}] result:[{}]", url, param, result);
            throw new ServerException(ResultConstant.Instance.LIST_INSTANCE_FAILED.setResult(url));
        }
        JsonNode instanceIds = jsonNode.get("result");
        if (instanceIds == null || instanceIds.size() == 0) {
            return new ArrayList<>(0);
        }
        List<String> resultList = new ArrayList<>();
        for (JsonNode instanceId : instanceIds) {
            resultList.add(instanceId.asText());
        }
        return resultList;
    }

    /**
     *
     * @param instanceId instanceId
     * @return  InstanceVo
     * @throws IOException 编译
     */
    public InstanceVo getInstance(String instanceId) throws IOException {
        String url = BaseHttpUtil.formatUrl(getInstanceUrl);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add(LocalConstant.API_HEADER_PARAM_KEY, accessServerUtil.generatorAccess());

        Map<String, String> param = new HashMap<>();
        param.put("instanceId", instanceId);
        HttpEntity httpEntity = new HttpEntity(JsonUtil.toJsonStr(param), headers);

        ResponseEntity<String> responseEntity;
        log.info("Instance Service getInstance url:{} pram:[{}]", url, param);
        try {
            responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);
        } catch (RestClientException e) {
            log.error(e.toString(), e);
            log.info("Instance Service getInstance Http error url:{} pram:[{}]", url, param);
            throw new ServerException(ResultConstant.Instance.CALL_INSTANCE_FAILED.setResult(url));
        }

        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            log.info("Instance Service getInstance HttpStatus not 200 url:{} pram:[{}] responseEntity:[{}]", url, param, responseEntity);
            return null;
        }
        String result = responseEntity.getBody();
        log.info("Instance Service getInstance HttpStatus result url:{} pram:[{}] result:[{}]", url, param, result);

        JsonNode jsonNode = MyUtil.MAPPER.readTree(result);
        if (!(jsonNode.has("errorCode") && "0x0".equalsIgnoreCase(jsonNode.get("errorCode").asText()))) {
            log.info("Instance Service getInstance HttpStatus result not success url:{} pram:[{}] result:[{}]", url, param, result);
            throw new ServerException(ResultConstant.Instance.LIST_INSTANCE_FAILED.setResult(url));
        }

        InstanceVo instance = JsonUtil.convertValue(jsonNode.get("result"), InstanceVo.class);
        return instance;
    }
}
